/********************************************************************************
**  (C) COPYRIGHT 2019
**	author	:	HuangZiBin
**  E-mail	:	635568706@qq.com
** 	version	:	1.0.0
**	If you find bugs, please send me an e-mail or contact me on qq.Thank you
********************************************************************************/
#include <stdio.h>
#include <string.h>

//#include "cmd_option.h"

#define OPTION_NAME_LEN (16)
	//#define OPTION_DATATYPE_LEN (5)
#define OPTION_VALUE_LEN (32)
#define OPTION_RESERVE (20)
	
#define OPTION_ERRORPRINT(fmt, args...) fprintf(stderr, fmt"\n", ##args)
	
struct CmdOptionElem {
	char option_name[OPTION_NAME_LEN];
//	char option_value[OPTION_VALUE_LEN];
	const char* option_desc;
	char* buf_ptr;
	int buf_size;
};

struct CmdOption {
	struct CmdOptionElem cmd_option[OPTION_RESERVE];
	int option_count;
};

static struct CmdOption g_cmd_option;


int option_add(char* option_name, const char* option_desc, char* buf_ptr, int buf_size)
{
	if (g_cmd_option.option_count >= OPTION_RESERVE) {
		OPTION_ERRORPRINT("option add failed, reason: already too many options");
		return -1;
	}
	struct CmdOptionElem* cmd_option = &g_cmd_option.cmd_option[g_cmd_option.option_count];
	if (snprintf(cmd_option->option_name, OPTION_NAME_LEN, "%s", option_name) >= OPTION_NAME_LEN) {
		OPTION_ERRORPRINT("buffer is too small for option:%s(len=%d), max_len:%d",
				option_name, strlen(option_name), OPTION_NAME_LEN);		
		return -1;
	};
	cmd_option->option_desc = option_desc;
	cmd_option->buf_ptr = buf_ptr;
	cmd_option->buf_size = buf_size;
	g_cmd_option.option_count++;
	return 0;
}
#if 0
char* option_get_value(char* option_name)
{
	int i = 0;
	for (i = 0; i < g_cmd_option.option_count; ++i) {
		if (strcmp(option_name, g_cmd_option.cmd_option[i].option_name) == 0) {
			return g_cmd_option.cmd_option[i].option_value;
		}
	}
	return NULL;
}
#endif
void option_show_usage()
{
	//printf("usage: %s [act=$action]\n", argv[0]);
	printf("support options:\n");
	int i = 0;
	for (i = 0; i < g_cmd_option.option_count; ++i) {
		printf("%s", g_cmd_option.cmd_option[i].option_name);
		printf("\t%s\n", g_cmd_option.cmd_option[i].option_desc);
		
	}
	return ;
}

static int match_cmd_arg(const char* opt_str, char* arg_string, char* target_buffer, int buffer_size)
{
	if (strncmp(opt_str, arg_string, strlen(opt_str)) == 0&&arg_string[strlen(opt_str)] == '=') {
		char* val_start_ptr = arg_string + strlen(opt_str) + 1;
		if (snprintf(target_buffer, buffer_size, "%s", val_start_ptr) >= buffer_size) {
			OPTION_ERRORPRINT("buffer(%d) is not big enough when parsing option:%s(len=%d)", buffer_size,
					opt_str, strlen(val_start_ptr));
			return -1;
		}
		if (target_buffer[0] == '"') {
			memmove(target_buffer, target_buffer+1, strlen(target_buffer));
			if (target_buffer[strlen(target_buffer)-1] == '"') {
				target_buffer[strlen(target_buffer)-1] = '\0';
			}
		}
		return 1;
	}
	return 0;
}


int option_parse(int argc, char** argv)
{
	int i = 0;
	int j = 0;
	int ret = 0;
	for (i = 1; i < argc; i++) {
		int match_flag = 0;
		for (j = 0; j < g_cmd_option.option_count; ++j) {		
			struct CmdOptionElem* cmd_option = &g_cmd_option.cmd_option[j];
			ret = match_cmd_arg(cmd_option->option_name, argv[i], 
							cmd_option->buf_ptr, cmd_option->buf_size);
			if (ret == 1) {
				match_flag = 1;
				break;
			}
		}
		if (match_flag == 0) {
			OPTION_ERRORPRINT("unrecongise option string:%s", argv[i]);
			OPTION_ERRORPRINT("unrecongise option string:%s", argv[i]);
			option_show_usage();
			//option_show_usage();
			return -1;
		}
	}
	return 0;
}

#if 0
char g_file_name[100] = "test.snd";
char g_speaker[3] = "1";
int main(int argc, char **argv)
{
	option_add("file", "specif a file to play", g_file_name, sizeof(g_file_name));
	option_add("speaker", "specif a speaker(1,2,3,default:1)", g_speaker, sizeof(g_speaker));
	if (option_parse(argc, argv) < 0) {
		return -1;
	}
	fprintf(stdout, "file:%s speaker:%s\r\n", g_file_name, g_speaker);
	return 0;
}
#endif